package cn.blnp.net.flowable.task.manually;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;

/**
 * <h3>手动任务</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/5/12 15:38
 */
@Slf4j
@SpringBootTest
public class ManuallyTaskTest {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;

    /**
     *  <p>
     *      手动任务指BPMN工作流引擎外部的任务，一般用于完善流程结构描述，不被工作流引擎执行。对工作流引擎而言，手动任务作为直接通过的活动处理。在Flowable中，
     *  手动任务作为一个空任务处理，当流程执行到此任务时直接离开继续流转流程。如果工作流引擎历史数据级别配置为activity、audit或full，工作流引擎会记录手动任务
     *  相关的流程历史数据。
     *  </p>
     *  <p>
     *      手动任务是预期在没有任何工作流引擎或应用帮助下执行的任务，用于建模那些工作流引擎无须关注的、由人所做的工作，通常指需要线下人工处理的活动，如由电话技术
     *  人员在客户位置安装电话。手动任务是一个自动执行的流程活动，工作流引擎仅记录相关的流程历史数据，无法通过taskService查询。定义格式如下所示：
     *  <pre>
     *      {@code
     *          <manualTask id="manualTask1" name="手动任务" />
     *      }
     *  </pre>
     *  </p>
     *  <h2>案例演示：</h2>
     *  <hr/>
     *  <p>
     *      该流程为奖品兑换流程：当客户发起流程提交“奖品兑换申请”后，先流转到“主办方审核”用户任务，操作完成后流转到“奖品发放”手动任务，任务自动流转直到流程结束。
     *      <b>流程定义文件：</b>{@link flow/manualTaskProcess.bpmn20.xml}<br/>
     *      <b>流程预览图：</b><br/>
     *      <img src="https://cdn4.winhlb.com/2025/05/12/6821a961d9398.png" />
     *  </p>
     **/
    @Test
    public void test() {
        Deployment deploy = repositoryService.createDeployment()
                .name("手动任务案例")
                .addClasspathResource("flow/manualTaskProcess.bpmn20.xml")
                .deploy();
        log.info("部署流程定义：{}", deploy.getId());
        ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        log.info("流程定义编号：{}", procDef.getId());
        //启动流程实例
        ProcessInstance procInst = runtimeService.startProcessInstanceById(procDef.getId());
        TaskQuery taskQuery = taskService.createTaskQuery()
                .processInstanceId(procInst.getId());

        //查询并完成第一个任务
        Task firstTask = taskQuery.singleResult();
        log.info("即将完成第一个任务，当前任务名称：{}", firstTask.getName());
        taskService.complete(firstTask.getId());
        //查询并完成第二个任务
        Task secondTask = taskQuery.singleResult();
        log.info("即将完成第二个任务，当前任务名称：{}", secondTask.getName());
        taskService.complete(secondTask.getId());
        //查询历史流程实例
        HistoricProcessInstance hisProcInst = historyService
                .createHistoricProcessInstanceQuery()
                .processInstanceId(procInst.getId())
                .singleResult();
        if (hisProcInst.getEndTime() != null) {
            log.info("当前流程已结束，结束时间：{}", DateUtil.formatDateTime(hisProcInst.getEndTime()));
        }

        /**
         *  演示结果：
         * 2025-05-12 15:57:55.751  INFO 87304 --- [           main] c.b.n.f.task.manually.ManuallyTaskTest   : 部署流程定义：cfd705b8-2f06-11f0-a2a9-50ebf6ec8f6d
         * 2025-05-12 15:57:55.758  INFO 87304 --- [           main] c.b.n.f.task.manually.ManuallyTaskTest   : 流程定义编号：manualTaskProcess:1:d024d79b-2f06-11f0-a2a9-50ebf6ec8f6d
         * 2025-05-12 15:57:55.925  INFO 87304 --- [           main] c.b.n.f.task.manually.ManuallyTaskTest   : 即将完成第一个任务，当前任务名称：奖品兑换申请
         * 2025-05-12 15:57:56.042  INFO 87304 --- [           main] c.b.n.f.task.manually.ManuallyTaskTest   : 即将完成第二个任务，当前任务名称：主办方审核
         * 2025-05-12 15:57:56.088  INFO 87304 --- [           main] c.b.n.f.t.m.ManualTaskExecutionListener  : 到达手动任务，当前节点名称：奖品发放，备注：这是手动任务，会自动完成
         * 2025-05-12 15:57:56.223  INFO 87304 --- [           main] c.b.n.f.t.m.ManualTaskExecutionListener  : 处理结果：(2025-05-12 15:57:56) 奖品线下发放完成！
         * 2025-05-12 15:57:56.287  INFO 87304 --- [           main] c.b.n.f.task.manually.ManuallyTaskTest   : 当前流程已结束，结束时间：2025-05-12 15:57:56
         **/
    }
}
